#include "adaboost.h"
#include <math.h>


void adaboost::initialize_distribution(double * d, double * y, int l) {
	for(int i = 0; i < l; i++) {
		d[i] = 1.0 / l;
	}
}

double adaboost::get_alpha(double * y, double * p, double * d, int l) {
	double error = get_error(y, p, d, l);
	double alpha = 0.5 * log((1-error)/error);
	return alpha;
}

// y in {-1, 1}
void adaboost::update_distribution(double alpha, double * y, double * p, int l, double * d_t, double * d_t1) {
	double z = 0;
	for(int i = 0; i < l; i++) {
		double h = get_h(p[i]);
		d_t1[i] = d_t[i] * exp(-alpha *y[i] * h);
		z += d_t1[i];
	}

	for(int i = 0; i < l; i++) {
		d_t1[i] /= z;
	}
}

// result in {-1, 1}
double adaboost::predict(double * alpha, double * p, int n) {
	double f = 0;
	for(int i = 0; i < n; i++) {
		double h = get_h(p[i]);
		f += alpha[i] * h;
	}
	double result = 1 / (1 + exp(-2 * f));
	return result;
}

bool adaboost::full_updating() {
	return true;
}

string adaboost::get_type() {
	return "adaboost";
}

double adaboost::get_error(double * y, double * p, double * d, int l) {
	double error = 0;
	for(int i = 0; i < l; i++) {
		double h = get_h(p[i]);
		if(y[i] != h) {
			error += d[i];
		}
	}
	return error;
}

double adaboost::get_h(double p) {
	return p > 0.5 ? 1 : -1;
}